using System;
using System.Net.Sockets;

namespace Cmpp.Client.Cmpp3Message.Utility {
    internal class DataConvert {
        private static uint sequenceId = 0u;

        public static uint CreateSequenceId() {
            InterlockedCounter.Increment(ref sequenceId);
            return sequenceId;
        }

        public static byte[] UInt32ToBytes(uint value) {
            value = HostToNetworkOrderExchange(value);
            return BitConverter.GetBytes(value);
        }

        public static uint BytesToUInt32(byte[] value) {
            uint result = BitConverter.ToUInt32(value, 0);
            return HostToNetworkOrderExchange(result);
        }

        public static uint BytesToUInt32(byte[] value, int startIndex) {
            uint result = BitConverter.ToUInt32(value, startIndex);
            return HostToNetworkOrderExchange(result);
        }

        public static byte[] UInt64ToBytes(ulong value) {
            value = HostToNetworkOrderExchange(value);
            return BitConverter.GetBytes(value);
        }

        public static ulong BytesToUInt64(byte[] value) {
            ulong result = BitConverter.ToUInt64(value, 0);
            return HostToNetworkOrderExchange(result);
        }

        public static string BytesToString(byte[] bytes) {
            return GlobalSettings.DefaultEncoding.GetString(bytes);
        }

        public static byte[] StringToBytes(string text) {
            return GlobalSettings.DefaultEncoding.GetBytes(text);
        }

        public static string GetTimeStampString(DateTime time) {
            return time.ToString("MMddhhmmss");
        }

        public static byte[] GetTimeStampBytes(DateTime time) {
            return StringToBytes(GetTimeStampString(time));
        }

        public static byte[] StringToUCS2Bytes(string text) {
            return GlobalSettings.UCS2Encoding.GetBytes(text);
        }

        public static byte[] StringToGBKBytes(string text) {
            return GlobalSettings.GBKEncoding.GetBytes(text);
        }

        public static string UCS2BytesToString(byte[] bytes) {
            return GlobalSettings.UCS2Encoding.GetString(bytes).Trim('\0');
        }

        public static string GBKBytesToString(byte[] bytes) {
            return GlobalSettings.GBKEncoding.GetString(bytes).Trim('\0');
        }

        public static string GetDateString(DateTime date) {
            return date.ToString("yyyyMMdd");
        }

        internal static void WriteToStream(byte[] bytes, NetworkStream stream) {
            if (stream.CanWrite) {
                stream.Write(bytes, 0, bytes.Length);
            }
        }

        public static short HostToNetworkOrderExchange(short host) {
            return (short) (((host & 0xff) << 8) | ((host >> 8) & 0xff));
        }

        public static int HostToNetworkOrderExchange(int host) {
            return
                (((HostToNetworkOrderExchange((short) host) & 0xffff) << 0x10)
                 | (HostToNetworkOrderExchange((short) (host >> 0x10)) & 0xffff));
        }

        public static long HostToNetworkOrderExchange(long host) {
            return
                ((HostToNetworkOrderExchange((int) host) & 0xffffffffL) << 0x20)
                | (HostToNetworkOrderExchange((int) (host >> 0x20)) & 0xffffffffL);
        }

        public static ushort HostToNetworkOrderExchange(ushort host) {
            return (ushort) (((host & 0xff) << 8) | ((host >> 8) & 0xff));
        }

        public static uint HostToNetworkOrderExchange(uint host) {
            return
                (((HostToNetworkOrderExchange((ushort) host) & 0xffffU) << 0x10)
                 | (HostToNetworkOrderExchange((ushort) (host >> 0x10)) & 0xffffU));
        }

        public static ulong HostToNetworkOrderExchange(ulong host) {
            return
                (((HostToNetworkOrderExchange((uint) host) & 0xffffffffUL) << 0x20)
                 | (HostToNetworkOrderExchange((uint) (host >> 0x20)) & 0XffffffffUL));
        }

        //[Obsolete]
        //public static byte[] ReadStreamToBytes(int Length, NetworkStream Stream) {
        //    byte[] bytes = null;
        //    if (Stream.CanRead) {
        //        if (Stream.DataAvailable) {
        //            bytes = new byte[Length];
        //            int l = 0;
        //            //lock (_SyncLockObject)
        //            {
        //                while (l < Length) {
        //                    int r;
        //                    r = Stream.Read(bytes, l, Length - l);
        //                    l += r;
        //                }
        //            }
        //        }
        //    }
        //    return bytes;
        //}

        //[Obsolete]
        //public static byte[] StructToBytes<TStruct>(TStruct @struct)
        //    where TStruct : struct {
        //    int size = Marshal.SizeOf(typeof (TStruct));
        //    IntPtr buffer = Marshal.AllocHGlobal(size);
        //    try {
        //        Marshal.StructureToPtr(@struct, buffer, false);
        //        byte[] bytes = new byte[size];
        //        Marshal.Copy(buffer, bytes, 0, size);
        //        return bytes;
        //    }
        //    finally {
        //        Marshal.FreeHGlobal(buffer);
        //    }
        //}

        //[Obsolete]
        //public static TStruct BytesToStruct<TStruct>(byte[] bytes) where TStruct : struct {
        //    if (bytes == null || bytes.Length == 0) {
        //        return default(TStruct);
        //    }

        //    int size = Marshal.SizeOf(typeof (TStruct));
        //    IntPtr buffer = Marshal.AllocHGlobal(size);
        //    try {
        //        Marshal.Copy(bytes, 0, buffer, size);
        //        return (TStruct) Marshal.PtrToStructure(buffer, typeof (TStruct));
        //    }
        //    finally {
        //        Marshal.FreeHGlobal(buffer);
        //    }
        //}
    }
}